﻿using KGySoft.Drawing.Imaging;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ttbit.form;

namespace bin.imgconv
{
    internal class lut
    {
        public static void CalcLUT(PalData pal, int palbegin, byte[] mapLutRGBA, byte[] mapLutIndex, bool quickLut, bool useParallel = false)
        {
            Color_Lab[] labc = new Color_Lab[256];
            Color[] croot = new Color[pal.paldata.Length / 4];
            for (var i = 0; i < croot.Length; i++)
            {
                var r = pal.paldata[i * 4 + 0];
                var g = pal.paldata[i * 4 + 1];
                var b = pal.paldata[i * 4 + 2];
                var a = pal.paldata[i * 4 + 3];

                croot[i] = Color.FromArgb(a, r, g, b);
                labc[i].FromRGB(r / 255.0f, g / 255.0f, b / 255.0f);
            }

            //多线程提升
            if (useParallel)
            {
                Parallel.For(0, 64, (j) =>
                {
                    for (var i = 0; i < 1024; i++)
                    {
                        byte R5 = (byte)((i >> 5) & 31);
                        byte G6 = (byte)j;// (byte)((i & 0x07E0) >> 5);
                        byte B5 = (byte)(i & 31);
                        Color_Lab ca = new Color_Lab();
                        ca.FromRGB(R5 / 31.0f, G6 / 63.0f, B5 / 31.0f);
                        double maxdist = double.MaxValue;
                        byte sameindex = 0;
                        for (var ci = palbegin; ci < croot.Length; ci++)
                        {
                            var dist = quickLut ? Color_Lab.QuickDist(ca, labc[ci]) : Color_Lab.ciede2000(ca, labc[ci]);
                            if (dist < maxdist)
                            {
                                maxdist = dist;
                                sameindex = (byte)ci;
                            }
                        }
                        int indexU = R5 * 32 + B5;
                        int index = G6 * 1024 + indexU;
                        mapLutIndex[index] = sameindex;
                        var samecolor = croot[sameindex];
                        if (mapLutRGBA != null)
                        {
                            mapLutRGBA[index * 4] = samecolor.R;
                            mapLutRGBA[index * 4 + 1] = samecolor.G;
                            mapLutRGBA[index * 4 + 2] = samecolor.B;
                            mapLutRGBA[index * 4 + 3] = samecolor.A;
                        }
                    }
                });
            }
            else
            {
                for (var i = 0; i < 65536; i++)
                {
                    byte R5 = (byte)((i >> 11) & 31);
                    byte G6 = (byte)((i >> 5) & 63);
                    byte B5 = (byte)(i & 31);//0~31
                    Color_Lab ca = new Color_Lab();
                    ca.FromRGB(R5 / 31.0f, G6 / 63.0f, B5 / 31.0f);
                    double maxdist = float.MaxValue;
                    byte sameindex = 0;
                    for (var ci = palbegin; ci < croot.Length; ci++)
                    {
                        var dist = quickLut ? Color_Lab.QuickDist(ca, labc[ci]) : Color_Lab.ciede2000(ca, labc[ci]);
                        if (dist < maxdist)
                        {
                            maxdist = dist;
                            sameindex = (byte)ci;
                        }
                    }
                    int indexU = R5 * 32 + B5;
                    int index = G6 * 1024 + indexU;
                    mapLutIndex[index] = sameindex;
                    var samecolor = croot[sameindex];
                    if (mapLutRGBA != null)
                    {
                        mapLutRGBA[index * 4] = samecolor.R;
                        mapLutRGBA[index * 4 + 1] = samecolor.G;
                        mapLutRGBA[index * 4 + 2] = samecolor.B;
                        mapLutRGBA[index * 4 + 3] = samecolor.A;
                    }
                }
            }
        }

    }
}
